using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;
using Soft2ApiDemo.Domain.Entity;
using Soft2ApiDemo.Domain.Repository;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using Soft2ApiDemo.Infrastructure.Utils;

namespace Soft2ApiDemo.Infrastructure.Filters
{
    public class CustomAuditLogFilter : IAsyncActionFilter
    {
        //AuditLog服务对象，用于保存/查询等操作
        private readonly IRepositoryBase<AuditLog> _auditLogService;

        //客户端信息接口，获取浏览器，IP等信息
        // private readonly IClientInfoProvider _clientInfoProvider;

        public CustomAuditLogFilter(
            IRepositoryBase<AuditLog> auditLogService
        )
        {
            _auditLogService = auditLogService;
            // _clientInfoProvider = clientInfoProvider;
        }

        public async Task
        OnActionExecutionAsync(
            ActionExecutingContext context,
            ActionExecutionDelegate next
        )
        {
            // // 判断是否写日志
            // if (!ShouldSaveAudit(context))
            // {
            //     await next();
            //     return;
            // }
            //接口Type
            var type =
                (context.ActionDescriptor as ControllerActionDescriptor)
                    .ControllerTypeInfo
                    .AsType();

            //方法信息
            var method =
                (context.ActionDescriptor as ControllerActionDescriptor)
                    .MethodInfo;

            //方法参数
            var arguments = context.ActionArguments;

            //开始计时
            var stopwatch = Stopwatch.StartNew();

            var auditInfo =
                new AuditLog {
                    UserId = 0,
                    UserName = "佚名",
                    //TruncateWithPostfix方法作用是截取字符串长度
                    ServiceName =
                        type != null
                            ? type
                                .FullName                             
                            : "",
                    //5.0版本以上，varchar(50)，指的是50字符，无论存放的是数字、字母还是UTF8汉字（每个汉字3字节），都可以存放50个。其他数据库要注意下这里
                    MethodName =
                        method
                            .Name
                            ,
                    //请求参数转Json
                    Parameters =JsonHelper.SerializeJson(arguments)
                            ,
                    ExecutionTime = DateTime.Now,
                    BrowserInfo = "你是一个小小小婆婆",
                    ClientIpAddress = "8888",
                    ClientName = "999"
                };

            ActionExecutedContext result = null;
            try
            {
                result = await next();
                if (result.Exception != null && !result.ExceptionHandled)
                {
                    auditInfo.Exception = result.Exception.ToString();
                }
            }
            catch (Exception ex)
            {
                auditInfo.Exception = ex.ToString();
                throw;
            }
            finally
            {
                stopwatch.Stop();
                auditInfo.ExecutionDuration =
                    Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds);

                if (result != null)
                {
                    switch (result.Result)
                    {
                        case ObjectResult objectResult:
                            auditInfo.ReturnValue =
                                JsonHelper.SerializeJson(objectResult.Value);
                            break;
                        case JsonResult jsonResult:
                            auditInfo.ReturnValue =
                                JsonHelper.SerializeJson(jsonResult.Value);
                            break;
                        case ContentResult contentResult:
                            auditInfo.ReturnValue = contentResult.Content;
                            break;
                    }
                }
                Console.WriteLine(auditInfo.ToString());
                auditInfo.ReturnValue =
                    auditInfo
                        .ReturnValue;

                //保存审计日志
                _auditLogService.Add(auditInfo);
            }
        }
    }
}
